/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2021 Marcus Britanicus (https://gitlab.com/marcusbritanicus)
 * Copyright (c) 2021 Abrar (https://gitlab.com/s96Abrar)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 **/

#include "DisplaySettings.hpp"
#include <wayqt/Registry.hpp>
#include <wayqt/WayQtUtils.hpp>
#include <wayqt/OutputManager.hpp>

#include <QDebug>

DisplaySettings::DisplaySettings() : QMainWindow() {
    WQt::Registry *reg = new WQt::Registry( WQt::Wayland::display() );

    reg->setup();

    opMgr = reg->outputManager();

    if ( not opMgr ) {
        qFatal( "Unable to start the output manager" );
    }

    opMgr->waitForDone();

    createGUI();
}


void DisplaySettings::createGUI() {
    outputs   = new QComboBox();
    enabled   = new QCheckBox();
    modes     = new QComboBox();
    rotations = new QComboBox();
    flipped   = new QCheckBox( "&Flipped" );

    rotations->addItems( { "Normal", "Rotate by 90", "Rotate by 180", "Rotate by 270" } );

    scale = new QSpinBox();
    posX  = new QSpinBox();
    posY  = new QSpinBox();

    connect(
        outputs, QOverload<int>::of( &QComboBox::currentIndexChanged ), [ = ]( int idx ) {
            /** Get the head */
            WQt::OutputHead *head = opMgr->heads().at( idx );

            /** IS this head enabled */
            enabled->setChecked( head->property( WQt::OutputHead::Enabled ).toBool() );

            /** If it's not enabled, then no point continuing. */
            if ( not enabled->isChecked() ) {
                return;
            }

            /** List the modes */
            modes->clear();
            for ( WQt::OutputMode *mode: head->property( WQt::OutputHead::Modes ).value<QList<WQt::OutputMode *> >() ) {
                QString modeStr = QString( "%1 x %2 @ %3 Hz" ).arg( mode->size().width() ).arg( mode->size().height() );
                modeStr         = modeStr.arg( mode->refreshRate() / 1000.0, 0, 'g', 3 );
                modeStr        += (mode->isPreferred() ? " *" : "");
                modes->addItem( modeStr );
            }

            /** Set the current mode */
            WQt::OutputMode *curMode = head->property( WQt::OutputHead::CurrentMode ).value<WQt::OutputMode *>();
            QString curModeStr       = QString( "%1 x %2 @ %3 Hz" ).arg( curMode->size().width() ).arg( curMode->size().height() );
            curModeStr  = curModeStr.arg( curMode->refreshRate() / 1000.0, 0, 'g', 3 );
            curModeStr += (curMode->isPreferred() ? " *" : "");
            modes->setCurrentText( curModeStr );

            /** Output scale */
            scale->setValue( head->property( WQt::OutputHead::Scale ).toInt() );

            /** Rotations */
            switch ( head->property( WQt::OutputHead::Transform ).toInt() ) {
                case 0: {
                    rotations->setCurrentIndex( 0 );
                    break;
                }

                case 1: {
                    rotations->setCurrentIndex( 1 );
                    break;
                }

                case 2: {
                    rotations->setCurrentIndex( 2 );
                    break;
                }

                case 3: {
                    rotations->setCurrentIndex( 3 );
                    break;
                }

                case 4: {
                    rotations->setCurrentIndex( 0 );
                    flipped->setChecked( true );
                    break;
                }

                case 5: {
                    rotations->setCurrentIndex( 1 );
                    flipped->setChecked( true );
                    break;
                }

                case 6: {
                    rotations->setCurrentIndex( 2 );
                    flipped->setChecked( true );
                    break;
                }

                case 7: {
                    rotations->setCurrentIndex( 3 );
                    flipped->setChecked( true );
                    break;
                }
            }

            /** Position */
            QPoint pos = head->property( WQt::OutputHead::Transform ).toPoint();
            posX->setValue( pos.x() );
            posY->setValue( pos.y() );
        }
    );

    for ( WQt::OutputHead *head: opMgr->heads() ) {
        outputs->addItem( head->property( WQt::OutputHead::Name ).toString() );
    }

    QFormLayout *baseLyt = new QFormLayout();

    baseLyt->addRow( "Output:",   outputs );
    baseLyt->addRow( "Enabled:",  enabled );
    baseLyt->addRow( "Modes:",    modes );
    baseLyt->addRow( "Scale:",    scale );
    baseLyt->addRow( "Rotation:", rotations );
    baseLyt->addRow( "",          flipped );

    QWidget     *posBase = new QWidget();
    QHBoxLayout *posLyt  = new QHBoxLayout();
    posLyt->addWidget( posX );
    posLyt->addWidget( posY );
    posBase->setLayout( posLyt );
    baseLyt->addRow( "Position", posBase );

    QToolButton *okayBtn = new QToolButton();
    okayBtn->setIcon( QIcon::fromTheme( "dialog-ok" ) );
    QToolButton *cancelBtn = new QToolButton();
    cancelBtn->setIcon( QIcon::fromTheme( "dialog-cancel" ) );

    QWidget     *btnBase = new QWidget();
    QHBoxLayout *btnLyt  = new QHBoxLayout();
    btnLyt->addWidget( okayBtn );
    btnLyt->addWidget( cancelBtn );
    btnBase->setLayout( btnLyt );
    baseLyt->addRow( "", btnBase );

    QWidget *w = new QWidget();
    w->setLayout( baseLyt );

    setCentralWidget( w );
}
